// 递归获取所有mesh
function getMesh (s, name) {
  s.forEach(v => {
    if (v.children && v.children.length > 0) {
      getMesh(v.children, name)
    } else {
      if (v instanceof THREE.Mesh) {
        if (name) {
          v.name = name[v.name]
        }
      }
    }
  })
}

// 更新div的位置
function renderDiv (object) {
  // 获取窗口的一半高度和宽度
  var halfWidth = window.innerWidth / 2
  var halfHeight = window.innerHeight / 2
  var vector = object.point.clone().project(camera)

  const getLabel = document.getElementById('label')

  // 修改 div 的位置
  getLabel.style.left = (vector.x * halfWidth + halfWidth) + 'px'
  getLabel.style.top = (-vector.y * halfHeight + halfHeight - object.object.position.y) + 'px'
  getLabel.style.display = 'block'
  // 显示模型信息
  getLabel.innerHTML = '我的名字是:' + object.object.name
}

let stats = new Stats()

// 初始化性能工具
function initStats () {
  stats.setMode(0) // 0: fps, 1: ms

  // 放在左上角
  stats.domElement.style.position = 'absolute'
  stats.domElement.style.left = '0px'
  stats.domElement.style.top = '0px'

  document.body.appendChild(stats.domElement)

  return stats
}

// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.outputEncoding = THREE.sRGBEncoding

// 场景
const scene = new THREE.Scene()
// scene.add(new THREE.AmbientLight(0xffffff))
scene.background = new THREE.Color(0xf0f0f0)
scene.add(new THREE.AmbientLight(0xf0f0f0))

// 坐标格辅助对象
const gridHelper = new THREE.GridHelper(2000, 100)
gridHelper.position.y = -1
gridHelper.material.opacity = 0.25
gridHelper.material.transparent = true
scene.add(gridHelper)
// 坐标轴
const axes = new THREE.AxesHelper(20)    // axes坐标轴对象
scene.add(axes)    // 把坐标轴添加到场景中去

// 相机
const camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000)
camera.position.set(160, 40, 10)
scene.add(camera)
// 相机辅助线
const helper = new THREE.CameraHelper(camera)
scene.add(helper)
// 相机拖拽控件
const controls = new THREE.OrbitControls(camera, renderer.domElement)
controls.enablePan = false //禁止右键拖拽
controls.update()

// 创建组对象，将导入的模型与立方体放置其中，统一添加且规避射线不识别的问题
const group = new THREE.Group()

// 创建加载器，加载外部模型
const loader = new THREE.GLTFLoader()

loader.load('qiuqiu.glb', function (gltf) {
  const name = {
    'mesh_id39': '男孩',
    'mesh_id41': '女孩',
    'node_id5': '球球'
  }
  gltf.scene.scale.set(10, 10, 10)
  gltf.scene.traverse(function (node) {
    if (node instanceof THREE.Mesh) { node.castShadow = true }
  })
  console.log(gltf.scene)
  getMesh(gltf.scene.children, name)
  group.add(gltf.scene)
}, function (xhr) {
  console.log((xhr.loaded / xhr.total * 100) + '% loaded')
}, function (error) {
  console.error(error)
})

// 添加立方体
// BoxGeometry立方体
const geometry = new THREE.BoxGeometry(5, 5, 5)
// MeshBasicMaterial 增加材质使立方体带有颜色
const material = new THREE.MeshLambertMaterial({ color: '#800080' })
// Mesh 将立方体放到网络
const cube = new THREE.Mesh(geometry, material)
cube.castShadow = true
cube.position.x = 10    // 立方体的坐标位置
cube.position.y = .5
cube.position.z = 0
cube.name = '立方体'
group.add(cube)

// 创建平面
let planeMaterial = new THREE.MeshPhongMaterial({ color: 0x808080, dithering: true })
let planeGeometry = new THREE.PlaneGeometry(2000, 2000)
let mesh = new THREE.Mesh(planeGeometry, planeMaterial)
mesh.position.set(0, -3, 0)
mesh.rotation.x = -Math.PI * 0.5
mesh.receiveShadow = true
scene.add(mesh)

// 添加光源
// 环境光
const ambient = new THREE.AmbientLight(0xffffff, 0.1)
scene.add(ambient)
// 聚光灯
const spotLight = new THREE.SpotLight(0xffffff, 1)
spotLight.position.set(15, 40, 35)
spotLight.angle = Math.PI / 4
spotLight.penumbra = 0.1
spotLight.decay = 2
spotLight.distance = 200

spotLight.castShadow = true
spotLight.shadow.mapSize.width = 512
spotLight.shadow.mapSize.height = 512
spotLight.shadow.camera.near = 10
spotLight.shadow.camera.far = 200
spotLight.shadow.focus = 1
scene.add(spotLight)
// 聚光灯辅助
lightHelper = new THREE.SpotLightHelper(spotLight)
scene.add(lightHelper)

let selectObject

// 渲染循环/动画循环-将内容真正的渲染到页面上
function animate () {
  if (selectObject != undefined && selectObject != null) {
    renderDiv(selectObject)
  }
  stats.update()
  controls.update()
  lightHelper.update()
  helper.update()
  requestAnimationFrame(animate)
  renderer.render(scene, camera)
}

// 添加组中的元素到场景中显示
scene.add(group)

initStats()
animate()

const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()

function onMouseClick (event) {
  event.preventDefault()
  //将鼠标点击位置的屏幕坐标转换成threejs中的标准坐标
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
  // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
  raycaster.setFromCamera(mouse, camera)
  // 获取raycaster直线和所有模型相交的数组集合
  // 是否检测后代元素
  var intersects = raycaster.intersectObjects(group.children, true)
  // var intersects = raycaster.intersectObjects(group.children)

  // 获取选中最近的 Mesh 对象
  if (intersects.length != 0 && intersects[0].object instanceof THREE.Mesh) {
    selectObject = intersects[0]
  } else {
    // alert('未选中 Mesh!')
  }
}

window.addEventListener('click', onMouseClick, false)

